package com.wjw.springsecuritydemo.config;

import com.wjw.springsecuritydemo.handler.MyAccessDeniedHandler;
import com.wjw.springsecuritydemo.handler.MyAuthenticationFailureHandler;
import com.wjw.springsecuritydemo.handler.MyAuthenticationSuccessHandler;
import com.wjw.springsecuritydemo.service.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyAccessDeniedHandler madh;
    @Autowired
    private UserDetailsServiceImpl userdetailsservice;
    @Autowired
    private DataSource dataSource;
    @Autowired
    private PersistentTokenRepository persistentTokenRepository;

    @Bean
    public PasswordEncoder getPw(){
        return new BCryptPasswordEncoder();
    }

    @Bean
    public PersistentTokenRepository getPersistentTokenRepository(){
        JdbcTokenRepositoryImpl jdbcTokenRepository=new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
        //自动建表,第一次启动需要 第二次会报错要注释
        //jdbcTokenRepository.setCreateTableOnStartup(true);
        return jdbcTokenRepository;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.formLogin()
                //自定义表单name
                //.usernameParameter("myself-username").passwordParameter("myself-password")
                //跟登录页面表单action地址对应，将地址识别为登录
                .loginProcessingUrl("/login")
                //.loginProcessingUrl("/main2")
                //自定义登录界面
                //.loginPage("/login.html")
                .loginPage("/alogin")
                //登录成功页面，必须是post请求,前后端分离不能用controller跳转
                .successForwardUrl("/toMain")
                .failureForwardUrl("/toError");
                //.successHandler(new MyAuthenticationSuccessHandler("main.html"))
                //.failureHandler(new MyAuthenticationFailureHandler("error.html"));

        //拦截
        //?匹配一个字符。*匹配0或多个字符。**匹配0或多个目录
        http.authorizeRequests()
                .antMatchers("/error.html").permitAll()
                //不需要被认证
                .antMatchers("/login.html").permitAll()
                //.antMatchers("/main2").permitAll()
                .antMatchers("/alogin").permitAll()
                .antMatchers("/main").permitAll()
                .antMatchers("/js/**","/css/**","/images/**").permitAll()
                .antMatchers("/**/*.png").permitAll()
                //分配权限页面
                .antMatchers("/main.html").hasAuthority(("admin"))
                .antMatchers("/main1.html").hasAnyAuthority("admin","normal")
                .antMatchers("/main2.html").hasRole("gm")
                //ip限制
                // .antMatchers("main1.html").hasIpAddress("127.0.0.1")
                //anyRequest任何请求都必须认证（登录）
                //.anyRequest().authenticated();
                //自定义拦截
                .anyRequest().access("@myServiceImpl.hasPermission(request,authentication)");

        //http.csrf().disable();

        //异常处理
        http.exceptionHandling().accessDeniedHandler(madh);

        http.rememberMe()
                //登录记住时间 秒
                //.tokenValiditySeconds(180)
                //自定义登录逻辑
                .userDetailsService(userdetailsservice)
                //持久层对象
                .tokenRepository(persistentTokenRepository);
    }

}
